home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / relay / hdrmunge.c < prev    next >
C/C++ Source or Header  |  1989-12-29  |  9KB  |  293 lines

  1. /*
  2.  * Usenet header modification & generation
  3.  *
  4.  * Ideally, headers should never be modified; message text, including
  5.  * headers, should be passed untouched.  Path: and Xref: demand that this
  6.  * rule be violated, and we delete huge obsolete headers to save space.
  7.  *
  8.  * Delete obsolete & large headers and Xref (can't be right),
  9.  * as headers are read.
  10.  *
  11.  * Recognise Newsgroups: and if more than one group, generate Xref: &
  12.  * leave holes for the article numbers - fileart will fill them in.
  13.  * (Make rn look in history instead?)
  14.  *
  15.  * Pile up headers into a static buffer until end of buffer (i.e. next
  16.  * line might not fit) [checked in hdrsave()], end of headers, end of
  17.  * file, or byte count is exhausted [checked in cparttofp].  Then write
  18.  * them to disk.  Prepend hostname! to Path: value, during output.
  19.  */
  20.  
  21. #define STAT(x)    /* fprintf(stderr,"%s, %d: ",__FUNC__,__LINE__);fprintf x */
  22.  
  23. #include <stdio.h>
  24. #ifndef AMIGA
  25. #  include <sys/types.h>
  26. #endif /* AMIGA */
  27. #include "libc.h"
  28. #include "news.h"
  29. #include "fileart.h"
  30. #include "headers.h"
  31. #include "article.h"
  32. #include "hdrint.h"
  33. #include "msgs.h"
  34.  
  35. /*
  36.  * HDRMEMSIZ is the length of a header-stashing buffer, which is used
  37.  * only during article-header copying.
  38.  *
  39.  * HDRMEMSIZ can be too small if memory is tight & will only hurt
  40.  * performance.
  41.  *
  42.  * Derivation: 630 bytes is a large header
  43.  *             (after discarding *-Version:, etc.).
  44.  */
  45. #ifndef HDRMEMSIZ
  46. #  ifdef SMALLMEM
  47. #    define HDRMEMSIZ 630
  48. #  else
  49. #    define HDRMEMSIZ 8192            /* # bytes for saving headers in core */
  50. #  endif    /* SMALLMEM */
  51. #endif    /* HDRMEMSIZ */
  52.  
  53. /* private */
  54. static char **hptrs = NULL;    /* saved-headers-ptrs array; allocated once */
  55.  
  56. /* forwards */
  57. FORWARD void emithdr(), hdrsave();
  58.  
  59. /*
  60.  * Generate an Xref: header from art->a_files.
  61.  * Turn slashes in art->a_files into colons in Xref:.
  62.  */
  63. void
  64. emitxref(art)
  65. register struct article *art;
  66. {
  67.     register char *slashp, *xrefs;
  68.  
  69.     if (!art->a_xref) {
  70.         art->a_xref = YES;
  71.         xrefs = strsave(art->a_files);
  72.         for (slashp = xrefs; (slashp = index(slashp, FNDELIM)) != NULL; )
  73.             *slashp++ = ':';
  74.         if (fprintf(art->a_artf, "%s %s %s\n",
  75.             xrefhdr.hdrnm, hostname(), xrefs) == EOF)
  76.             fulldisk(art, spoolnm(art));
  77.         free(xrefs);
  78.     }
  79. }
  80.  
  81. /*
  82.  * --- header copying starts here ---
  83.  */
  84.  
  85. /*
  86.  * Copy headers and delete or modify a few.  Assumes hdrparse has been
  87.  * called.  Delete obsolete & large headers and Xref.  Pile up other
  88.  * headers for later output (Path: is changed during output).
  89.  *
  90.  * art->a_artf may be NULL, and may get set by hdrsave.
  91.  */
  92.  
  93. STATIC void hdrmunge(art, buffer, hdrlen, hdrlst)
  94. register struct article *art;
  95. register char *buffer;
  96. int hdrlen;            /* optimization only */
  97.  
  98. /* headers of negative utility: snuff 'em */
  99. struct hdrdef *hdrlst[];
  100. {
  101.     register struct hdrdef **vhp;
  102.  
  103.     if (headdebug)
  104.         (void) fputs(buffer, stderr);
  105.     for (vhp = hdrlst; *vhp != NULL; vhp++)
  106.         if (STREQN(buffer, (*vhp)->hdrnm, (int)(*vhp)->hdrlen))
  107.             return;            /* don't save this header */
  108.     hdrsave(art, buffer, hdrlen);
  109. }
  110.  
  111. /*
  112.  * If headers already dumped, just write to art->a_artf.
  113.  * Else if there is room, stash "hdr" away until end of headers is seen
  114.  * (could just wait until Newsgroups: and Control: are seen, if seen)
  115.  * or there is no room left in the header buffer, then open the first
  116.  * article link (on art->a_artf) and dump the saved headers and the current
  117.  * header to it.
  118.  *
  119.  * Copy into art->a_haccum (in future, could read in directly,
  120.  * iff copying is high on the profile).
  121.  *
  122.  * hdrstore is static because it is used repeatedly, it only makes sense
  123.  * to have one active at a time, and there is no memory saving in allocating
  124.  * and deallocating it, particularly since copyart's (header) buffer must
  125.  * coexist with hdrstore.
  126.  */
  127.  
  128. STATIC void hdrsave(art, hdr, hdrlen)
  129. register struct article *art;
  130. char *hdr;
  131. register int hdrlen;            /* optimization only */
  132. {
  133.     if (art->a_artf != NULL) {
  134.         emithdr(art, hdr, hdrlen);
  135.         return;
  136.     }
  137.     if (art->a_haccum == NULL) {
  138.         static char hdrstore[HDRMEMSIZ];
  139.  
  140.         art->a_haccum = hdrstore;
  141.         art->a_haccum[0] = '\0';
  142.         art->a_hnext = art->a_haccum;
  143.         art->a_hbytesleft = HDRMEMSIZ;
  144.     }
  145.     if (art->a_hbytesleft > hdrlen) {
  146.         /* add new ptr.-to-this-header to tail of saved-hdr-ptr.-list */
  147.         if (art->a_hptrs == NULL) {
  148.             art->a_hpused = 0;
  149.             art->a_hpalloced = MINSHPTRS;
  150.             if (hptrs == NULL)    /* once only */
  151.                 hptrs = (char **) nemalloc((unsigned)
  152.                     (art->a_hpalloced * sizeof(char *)));
  153.             art->a_hptrs = hptrs;
  154.         }
  155.         while (art->a_hpused >= art->a_hpalloced) {
  156.             art->a_hpalloced += MINSHPTRS;
  157.             art->a_hptrs = hptrs = (char **)
  158.                 realloc((char *)art->a_hptrs, (unsigned)
  159.                 (art->a_hpalloced * sizeof(char *)));
  160.             if (art->a_hptrs == NULL)
  161.                 errunlock("out of memory (for art->a_hptrs)", "");
  162.         }
  163.         art->a_hptrs[art->a_hpused++] = art->a_hnext;
  164.  
  165.         /* (void) strcat(art->a_haccum, hdr); */
  166.         (void) strcpy(art->a_hnext, hdr);
  167.         art->a_hnext += hdrlen;        /* points at NUL byte */
  168.         art->a_hbytesleft -= hdrlen;
  169.     } else {
  170.         hdrdump(art, NOTALLHDRS);    /* don't file */
  171.         if (art->a_artf != NULL)
  172.             emithdr(art, hdr, hdrlen);
  173.     }
  174. }
  175.  
  176. /*
  177.  * Change Path: while writing it out, just dump other headers (hdr) verbatim.
  178.  */
  179.  
  180. STATIC void emithdr(art, hdr, hdrlen)
  181. register struct article *art;
  182. char *hdr;
  183. register int hdrlen;
  184. {
  185.     if (STREQN(hdr, pathhdr.hdrnm, (int)pathhdr.hdrlen)) {
  186.         register char *oldpath, *hostnm = hostname();
  187.  
  188.         oldpath = skipsp(&hdr[pathhdr.hdrlen]);
  189.         /*
  190.          * V7 f?printf return 0 or EOF, not a byte count, so it is
  191.          * not portable to use fprintf's return value as a byte count.
  192.          */
  193.         if (fprintf(art->a_artf, "%s %s!", pathhdr.hdrnm, hostnm) ==
  194.                 EOF || fputs(oldpath, art->a_artf) == EOF)
  195.             fulldisk(art, spoolnm(art));
  196.         else {
  197.             static unsigned hostlen = 0;
  198.  
  199.             if (hostlen == 0)
  200.                 hostlen = strlen(hostnm);
  201.             art->a_charswritten += pathhdr.hdrlen + STRLEN(" ") +
  202.                 hostlen + STRLEN("!") + strlen(oldpath);
  203.         }
  204.     } else {
  205.         if (fwrite(hdr, hdrlen, 1, art->a_artf) != 1)
  206.             fulldisk(art, spoolnm(art));
  207.         else
  208.             art->a_charswritten += hdrlen;
  209.     }
  210. }
  211.  
  212. /*
  213.  * Write out saved headers after opening on art->a_artf either a temporary
  214.  * file (using mktemp(3)) or the first article link, based on art->h.h_ngs &
  215.  * nxtartnum(); set a_tmpf to which ever name is opened.
  216.  * Modify Path: value on the way.
  217.  *
  218.  * If all headers were seen, then open the first link, link to the rest,
  219.  * and generate Xref:, else open a temporary name and write the article
  220.  * there (it will get filed later by hdrdump(...,ALLHDRS) or in insart()).
  221.  */
  222.  
  223. void hdrdump(art, allhdrsseen)
  224. register struct article *art;
  225. boolean allhdrsseen;        /* all headers seen & hdrdeflt() called? */
  226. {
  227.     STAT((stderr,"article%s filed\n", art->a_filed ? "" : " NOT"));
  228.     if (art->a_filed)
  229.         return;
  230.     STAT((stderr,"all headers%s seen\n", allhdrsseen ? "" : " NOT"));
  231.     if (allhdrsseen)
  232.         fileart(art);            /* set a_tmpf */
  233.     else if (art->a_artf == NULL) {
  234.         nnfree(&art->a_tmpf);
  235.         art->a_tmpf = strsave(SPOOLTMP);
  236.         (void) mktemp(art->a_tmpf);
  237.         art->a_unlink = YES;
  238.         art->a_artf = fopenwclex(art->a_tmpf, "w");
  239.         if (art->a_artf == NULL)
  240.             art->a_status |= ST_DROPPED;
  241.     }
  242.     STAT((stderr,"art->a_tmpf = `%s'\n", art->a_tmpf));
  243.     if (art->a_artf != NULL &&
  244.             art->a_haccum != NULL && art->a_haccum[0] != '\0') {
  245.         register int i;
  246.         register char **pp;
  247.         register char *nxtln;
  248.         register int saved;
  249.  
  250.         for (i = 0, pp = art->a_hptrs; i < art->a_hpused; ++i, ++pp) {
  251.             if (i >= art->a_hpused-1)    /* last in-core hdr? */
  252.                 nxtln = art->a_hnext;
  253.             else
  254.                 nxtln = pp[1];
  255.             saved = *nxtln;
  256.             *nxtln = '\0';
  257.             emithdr(art, *pp, nxtln - *pp);
  258.              *nxtln = saved;                /* restore */
  259.         }
  260.         /* art->a_haccum could be freed and zeroed here, if malloced */
  261.         art->a_haccum[0] = '\0';        /* paranoia */
  262.         art->a_hnext = art->a_haccum;    /* for next article */
  263.         art->a_hpused = 0;                /* trash saved-header-ptr-list */
  264.  
  265.         /* reduce saved-header-ptr-list to original size */
  266.         if (art->a_hpalloced > MINSHPTRS) {
  267.             art->a_hpalloced = MINSHPTRS;
  268.             art->a_hptrs = hptrs = (char **)
  269.                 realloc((char *)art->a_hptrs,
  270.                     (unsigned) (art->a_hpalloced * sizeof(char *)));
  271.             if (hptrs == NULL)
  272.                 errunlock("can't free a_hptrs memory", "");
  273.         }
  274.     }
  275. }
  276.  
  277. /*
  278.  * hdrparse remembers this header if it's interesting.
  279.  * hdrmunge needs art->h.h_ngs to be set, so it is called second.
  280.  * hdrmunge saves or writes this header, unless it's deemed a waste of bytes.
  281.  * hdrmunge may call hdrdump(art, NOTALLHDRS).
  282.  * hdrdump counts art->a_charswritten.
  283.  */
  284.  
  285. void hdrdigest(art, line, hdrlen)
  286. register struct article *art;
  287. register char *line;
  288. int hdrlen;
  289. {
  290.      hdrparse(&art->h, line, parsehdrs);
  291.     hdrmunge(art, line, hdrlen, hdrvilest);
  292. }
  293.